#include "bonddealchart.h"
#include <bondlib/BondDeal/PanoramicBondDealContainer.h>
#include <core/comdefs.h>
#include <core/StyleMgr.h>
#include <qbtools/tools.h>
#include <uam/ServerTimeMgr.h>
#include <widgets/chart/basechart_plot.h>
#include <widgets/chart/basechart_graph.h>
#include <widgets/STips.h>

#define min(a,b)            (((a) < (b)) ? (a) : (b))
#define max(a,b)            (((a) > (b)) ? (a) : (b))

using namespace qb;
BondDealChart::BondDealChart(QWidget* parent)
	: QWidget(parent)
	, m_type(type_gov)
	, m_lRemain(-1)
	, m_nLinePNum(0)
	, m_nPointNum(0)
	, m_nHotPoint(-1)
{
	m_clrInHour.setRgb(0, 128, 253);
	m_clrOutHour.setRgb(0, 223, 85);


	m_clrCyan = StyleMgr::instance().color("Cyan05");
	m_clrVolcano = StyleMgr::instance().color("Volcano05");
	m_clrGeekBlue = StyleMgr::instance().color("Geekblue05");
	m_clrYellow = StyleMgr::instance().color("Yellow05");
	m_clrMagenta = StyleMgr::instance().color("Magenta05");
	m_clrGreen = StyleMgr::instance().color("Green05");
}

BondDealChart::~BondDealChart()
{
}

void BondDealChart::loadDealData()
{
	CPanoramicBondDealMap& dealMap = CPanoramicBondDealContainer::instance().GetDealMap();
}

void BondDealChart::updateDealData(QList<xQBPanoramicMarketStreamUnit>& lstData)
{
	refreshData();
}

// 	void BondDealChart::loadData(CAnalysisYieldCurve* pYieldCurve, int remain)
// 	{
// 		m_lRemain = remain;
// 		inputData(pYieldCurve);
// 		refreshData();
// 	}

void BondDealChart::setType(emtype type)
{
	m_type = type;
	if (m_type == type_gov)
	{
		m_dOriginMaxX = 50.0;
		bcte->setText("中债国债","中债国开","国开","非国开","国债","地方债");
	}
	else
	{
		m_dOriginMaxX = 10.0;
		bcte->setText("", "", "AAA+", "AAA", "AA+", "AA及以下");
	}
}

void BondDealChart::setLeftDrag(double ratio)
{
	m_dRatioBegin = ratio;
	if (m_dRatioBegin < 0.01)m_dRatioBegin = 0.0;
	refreshData();
}

void BondDealChart::setRightDrag(double ratio)
{
	m_dRatioEnd = ratio;
	refreshData();
}

void BondDealChart::setCentralDrag(double ratio1, double ratio2)
{
	m_dRatioBegin = ratio1;
	m_dRatioEnd = ratio2;
	if (m_dRatioBegin < 0.01)m_dRatioBegin = 0.0;
	refreshData();
}

void BondDealChart::createChart()
{
	verticalLayout = new QVBoxLayout(this);
	customPlot = new BaseChartCustomPlot(this);
	verticalLayout->addWidget(customPlot);
	this->setLayout(verticalLayout);

	connect(customPlot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(onMouseMove(QMouseEvent*)));
	connect(customPlot, &BaseChartCustomPlot::mouseDoubleClick, [=]() { emit mouseDoubleClick(this); });

	QBrush boxBrush(StyleMgr::instance().color("BasicPlate"));
	customPlot->setBackground(boxBrush);
	customPlot->addGraph(customPlot->xAxis, customPlot->yAxis);
	customPlot->xAxis->grid()->setCustomAxisGrid(this);
	customPlot->yAxis->grid()->setCustomAxisGrid(this);
	customPlot->xAxis->setYAxis(customPlot->yAxis);
	customPlot->yAxis->setTickLabelPadding(40);

	customPlot->graph(0)->setPen(QPen(m_clrYellow));
	customPlot->graph(0)->setLineStyle(BaseChartGraph::lsLine);
	customPlot->graph(0)->setScatterStyle(BaseChartScatterStyle(BaseChartScatterStyle::ssCircle, 3));

	customPlot->addGraph(customPlot->xAxis, customPlot->yAxis);
	customPlot->graph(1)->setPen(QPen(m_clrCyan));
	customPlot->graph(1)->setLineStyle(BaseChartGraph::lsLine);
	customPlot->graph(1)->setScatterStyle(BaseChartScatterStyle(BaseChartScatterStyle::ssCircle, 3));

	customPlot->addGraph(customPlot->xAxis, customPlot->yAxis);
	customPlot->graph(2)->setPen(QPen(m_clrVolcano));
	customPlot->graph(2)->setLineStyle(BaseChartGraph::lsNone);
	customPlot->graph(2)->setScatterStyle(BaseChartScatterStyle(BaseChartScatterStyle::ssDisc, 2));

	customPlot->addGraph(customPlot->xAxis, customPlot->yAxis);
	customPlot->graph(3)->setPen(QPen(m_clrGeekBlue));
	customPlot->graph(3)->setLineStyle(BaseChartGraph::lsNone);
	customPlot->graph(3)->setScatterStyle(BaseChartScatterStyle(BaseChartScatterStyle::ssDisc, 2));

	customPlot->addGraph(customPlot->xAxis, customPlot->yAxis);
	customPlot->graph(4)->setPen(QPen(m_clrMagenta));
	customPlot->graph(4)->setLineStyle(BaseChartGraph::lsNone);
	customPlot->graph(4)->setScatterStyle(BaseChartScatterStyle(BaseChartScatterStyle::ssDisc, 2));

	customPlot->addGraph(customPlot->xAxis, customPlot->yAxis);
	customPlot->graph(5)->setPen(QPen(m_clrGreen));
	customPlot->graph(5)->setLineStyle(BaseChartGraph::lsNone);
	customPlot->graph(5)->setScatterStyle(BaseChartScatterStyle(BaseChartScatterStyle::ssDisc, 2));

	customPlot->xAxis->setNumberPrecision(4);
	customPlot->xAxis->setCustomGrid();
	customPlot->yAxis->setCustomGrid();
	customPlot->xAxis->setSubTicks(false);
	customPlot->yAxis->setSubTicks(false);
	customPlot->yAxis->ticker()->setTickCount(4);

	bcte = new BaseChartTextElement(customPlot, "", QFont("Microsoft YaHei", 9, QFont::Bold));
	bcte->setCustomDraw(this);
	bcte->setTextFlags(Qt::AlignLeft | Qt::AlignVCenter);
	bcte->setTextOffset(18);
	bcte->setTextColor(StyleMgr::instance().color("TextNormal"));
	customPlot->plotLayout()->addElement(1, 0, bcte);

	bcde = new BaseChartDragBarElement(customPlot);
	customPlot->plotLayout()->addElement(2, 0, bcde);

	refreshData();
}

bool BondDealChart::drawGridXLines(BaseChartPainter* painter)
{
	if (m_type == type_gov)
	{
		if (m_vctGridX.size() != 11)
		{
			m_vctGridX.clear();
			m_vctGridX.push_back(0);
			m_vctGridX.push_back(1);
			m_vctGridX.push_back(2);
			m_vctGridX.push_back(3);
			m_vctGridX.push_back(5);
			m_vctGridX.push_back(7);
			m_vctGridX.push_back(10);
			m_vctGridX.push_back(15);
			m_vctGridX.push_back(20);
			m_vctGridX.push_back(30);
			m_vctGridX.push_back(50);
		}
	}
	else
	{
		if (m_vctGridX.size() != 8)
		{
			m_vctGridX.clear();
			m_vctGridX.push_back(0);
			m_vctGridX.push_back(1);
			m_vctGridX.push_back(2);
			m_vctGridX.push_back(3);
			m_vctGridX.push_back(4);
			m_vctGridX.push_back(5);
			m_vctGridX.push_back(7);
			m_vctGridX.push_back(10);
		}
	}

	int top = customPlot->yAxis->axisRect()->top();
	int bottom = customPlot->yAxis->axisRect()->bottom();

	QString szText;
	QFont font("Microsoft YaHei");
	font.setPixelSize(12);
	painter->setFont(font);

	int i = 0;
	for(auto x : m_vctGridX)
	{
		int X = customPlot->xAxis->coordToPixel(x);
		if (X >= customPlot->xAxis->axisRect()->left() && X <= customPlot->xAxis->axisRect()->right())
		{
			painter->drawLine(QLineF(X, bottom, X, top));
			
			if(i==0)
				szText = QString::asprintf("%d", (int)x);
			else 
				szText = QString::asprintf("%dY", (int)x);

			int nFlag = Qt::TextDontClip | Qt::AlignCenter | Qt::AlignVCenter;
			QRectF rect(0, 0, 10000, 10000);
			QRectF measureRect = painter->boundingRect(rect, nFlag, szText);
			QPen oldPen = painter->pen();
			painter->setPen(QColor(128, 128, 128, 255));
			painter->drawText(X - measureRect.width() / 2, bottom, measureRect.width(), measureRect.height(), nFlag, szText);
			painter->setPen(oldPen);
		}
		i++;
	}

	return true;
}

bool BondDealChart::drawGridYLines(BaseChartPainter* painter)
{
	QString szValue;
	QRectF rfText;
	int i = 0;
	int nTextTop = 10000;//纵轴刻度文字
	int top = customPlot->yAxis->axisRect()->top();
	int bottom = customPlot->yAxis->axisRect()->bottom();
	int tickCount = (customPlot->yAxis->ticker()->tickCount() == 0 ? 5 : customPlot->yAxis->ticker()->tickCount());
	double step = (m_dMaxY - m_dMinY) / tickCount;
	double minY = m_dMinY;
	double maxY = m_dMaxY;
	QRectF rect(0, 0, 10000, 10000);
	int nFlag = Qt::TextDontClip | Qt::AlignLeft | Qt::AlignVCenter;

	while (1)
	{
		float price = m_dMinY + step * i;
		int Y = customPlot->yAxis->coordToPixel(price);
		if (Y < top - 1 || Y > bottom) break;
		if (Y <= bottom)
		{
			painter->drawLine(QLineF(customPlot->xAxis->axisRect()->left() - customPlot->yAxis->tickLabelPadding(), Y, customPlot->xAxis->axisRect()->right(), Y));
			if (((int)(step * 100)) % 10 > 0 || ((int)(minY * 100)) % 10 > 0 || ((int)(maxY * 100)) % 10 > 0) szValue = QString("%1").arg(price, 0, 'f', 2, '0');
			else szValue = QString("%1").arg(price, 0, 'f', 1, '0');

			QRectF measureRect = painter->boundingRect(rect, nFlag, szValue);
			if (nTextTop > Y + measureRect.height())
			{
				QPen oldPen = painter->pen();
				painter->setPen(QColor(128, 128, 128, 255));
				painter->drawText(customPlot->xAxis->axisRect()->left() - customPlot->yAxis->tickLabelPadding() + 2, Y - measureRect.height(), measureRect.width(), measureRect.height(), nFlag, szValue);
				painter->setPen(oldPen);
				nTextTop = Y - measureRect.height();
			}
		}
		i++;
		if (i > 100)
			break;
	}

	return true;
}

bool BondDealChart::customDraw(BaseChartPainter* painter, const QRect& rect)
{
	int count = 6;
	if (m_type == type_credit)count = 4;

	QColor clrBack(38, 55, 53);
	QRect rectBK = rect;
	int i = 1;
	if (m_type == type_gov)
	{
		rectBK.setRight(rect.left() + rect.width() * i / count - 2);
		painter->fillRect(rectBK, clrBack);
		painter->setPen(m_clrYellow);
		int x = rectBK.left() + 6;
		int y = rectBK.top() + rectBK.height() / 2;
		painter->drawLine(QLineF(x, y, x + 8, y));
		painter->drawLine(QLineF(x, y + 1, x + 8, y + 1));
		rectBK.setLeft(rectBK.right() + 4);
		i++;

		rectBK.setLeft(rectBK.right() + 4);
		rectBK.setRight(rect.left() + rect.width() * i / count - 2);
		painter->fillRect(rectBK, clrBack);
		painter->setPen(m_clrCyan);
		x = rectBK.left() + 4;
		y = rectBK.top() + rectBK.height() / 2;
		painter->drawLine(QLineF(x, y, x + 8, y));
		painter->drawLine(QLineF(x, y + 1, x + 8, y + 1));
		rectBK.setLeft(rectBK.right() + 4);
		i++;
	}

	rectBK.setRight(rect.left() + rect.width() * i / count - 2);
	painter->fillRect(rectBK, clrBack);
	painter->setPen(m_clrVolcano);
	painter->setBrush(m_clrVolcano);
	int x = rectBK.left() + 4;
	int y = rectBK.top() + rectBK.height() / 2 - 2;
	painter->drawEllipse(x, y, 6, 6);
	rectBK.setLeft(rectBK.right() + 4);
	i++;

	rectBK.setRight(rect.left() + rect.width() * i / count - 2);
	painter->fillRect(rectBK, clrBack);
	painter->setPen(m_clrGeekBlue);
	painter->setBrush(m_clrGeekBlue);
	x = rectBK.left() + 4;
	y = rectBK.top() + rectBK.height() / 2 - 2;
	painter->drawEllipse(x, y, 6, 6);
	rectBK.setLeft(rectBK.right() + 4);
	i++;

	rectBK.setRight(rect.left() + rect.width() * i / count - 2);
	painter->fillRect(rectBK, clrBack);
	painter->setPen(m_clrMagenta);
	painter->setBrush(m_clrMagenta);
	x = rectBK.left() + 4;
	y = rectBK.top() + rectBK.height() / 2 - 2;
	painter->drawEllipse(x, y, 6, 6);
	rectBK.setLeft(rectBK.right() + 4);
	i++;

	rectBK.setRight(rect.left() + rect.width() * i / count - 2);
	painter->fillRect(rectBK, clrBack);
	painter->setPen(m_clrGreen);
	painter->setBrush(m_clrGreen);
	x = rectBK.left() + 4;
	y = rectBK.top() + rectBK.height() / 2 - 2;
	painter->drawEllipse(x, y, 6, 6);
	return true;
}

// 	void BondDealChart::inputData(CAnalysisYieldCurve* pYieldCurve)
// 	{
// 		CAnalysisYieldCurve* pData = (CAnalysisYieldCurve*)pYieldCurve;
// 		clearCurrentCurve();
// 		if (!pData) 
// 		{
// 			return;
// 		}
// 
// 	//	m_chartDistData.m_Stream.m_list = pData->m_Stream.m_list;
// 		FIELDCOPY(m_chartDistData.m_Curve.m_CurveName, pData->m_Curve.m_CurveName);
// 		FIELDCOPY(m_chartDistData.m_Curve.m_CurveType, pData->m_Curve.m_CurveType);
// 		FIELDCOPY(m_chartDistData.m_Curve.m_CurveName_En, pData->m_Curve.m_CurveName_En);
// 		m_chartDistData.m_Curve.m_Date = pData->m_Curve.m_Date;
// 
// 		if (type_All == m_type)
// 		{
// 			m_chartDistData.m_Curve.m_List = pData->m_Curve.m_List;
// 			m_chartDistData.m_Stream.m_list.clear();
// 			return;
// 		}
// 		else
// 		{
// 			const int cn_near_number = 4;
// 			if (pData->m_Curve.m_List.size() <= cn_near_number) {
// 				m_chartDistData.m_Curve.m_List = pData->m_Curve.m_List;
// 				return;
// 			}
// 			std::map<int, std::list<xQBAYieldCurveUnit_c>> mapCurve;
// 			for (std::list<xQBAYieldCurveUnit_c>::const_iterator itr = pData->m_Curve.m_List.begin();
// 				itr != pData->m_Curve.m_List.end(); itr++) {
// 				mapCurve[abs(GetDate(itr->m_Period) - m_lRemain)].push_back(*itr);
// 			}
// 			int nLoop = 0;
// 			for (std::map<int, std::list<xQBAYieldCurveUnit_c>>::const_iterator itrMp = mapCurve.begin();
// 				itrMp != mapCurve.end(); itrMp++) {
// 				if (nLoop >= cn_near_number) break;
// 				for (std::list<xQBAYieldCurveUnit_c>::const_iterator itUnit = itrMp->second.begin();
// 					itUnit != itrMp->second.end(); itUnit++) {
// 					m_chartDistData.m_Curve.m_List.push_back(*itUnit);
// 					nLoop++;
// 					if (nLoop >= cn_near_number) break;
// 				}
// 			}
// 		}
// 	}

void BondDealChart::refreshData()
{
	m_dMaxX = m_dOriginMaxX * m_dRatioEnd;
	m_dMinX = m_dOriginMaxX * m_dRatioBegin;

	if (customPlot)customPlot->xAxis->setRange(m_dMinX, m_dMaxX + (m_dMaxX - m_dMinX) / 50);

	// 		QB_CHECK_RETURN_VOID1(customPlot && customPlot->graph(0) && customPlot->graph(1) && customPlot->graph(2) && bcte && bcde);
	// 
	// 		m_CurveShow.clear();
	// 		m_StreamShow.clear();
	// 
	// 		BONDRATE br;
	// 		QString szTemp, szUnit, szValue;
	// 		std::list<xQBAYieldCurveUnit_c>::const_iterator it;
	// 		for (it = m_chartDistData.m_Curve.m_List.begin(); it != m_chartDistData.m_Curve.m_List.end(); it++) {
	// 			szTemp = it->m_Period;
	// 			szUnit = szTemp.right(1);
	// 			if (szUnit == "D") {
	// 				szValue = szTemp.left(szTemp.length() - 1);
	// 				br.expire = szValue.toFloat() * 4 / 365;
	// 			}
	// 			else if (szUnit == "M") {
	// 				szValue = szTemp.left(szTemp.length() - 1);
	// 				br.expire = szValue.toFloat() * 4 / 12;
	// 			}
	// 			else if (szUnit == "Y") {
	// 				szValue = szTemp.left(szTemp.length() - 1);
	// 				br.expire = szValue.toFloat();
	// 				if (br.expire > 0.5)br.expire += 3;
	// 			}
	// 			else {
	// 				szValue = szTemp;
	// 				br.expire = szValue.toFloat();
	// 				//	if (br.expire > 0.5)br.expire += 3;
	// 			}
	// 			br.price = it->m_Yield;
	// 			m_CurveShow.push_back(br);
	// 		}
	// 		m_CurveShow.sort();
	// 
	// 		if (m_CurveShow.size() < 6)
	// 		{
	// 			bcde->setEnable(false);
	// 		}
	// 		else
	// 		{
	// 			bcde->setEnable(true);
	// 		}
	// 
	// 		bool bFirst = false;
	// 		if (0.0 == m_dOriginMaxX)
	// 		{
	// 			bFirst = true;
	// 		}
	// 
	// 		m_dOriginMaxX = max(m_dOriginMaxX, m_CurveShow.size() - 1);
	// 		m_dOriginMaxX = min(m_dOriginMaxX, m_CurveShow.size() - 1);
	// 
	// 		int begin = 0, end = 0;
	// 		if (type_All == m_type)
	// 		{
	// 			begin = m_nBegin;
	// 			end = m_nEnd;
	// 		}
	// 		else
	// 		{
	// 			begin = m_nDealBegin;
	// 			end = m_nDealEnd;
	// 		}
	// 
	// 		if (begin > 0 && begin < (int)m_CurveShow.size() - 1)
	// 		{
	// 			auto itBegin = m_CurveShow.begin();
	// 			auto itEnd = m_CurveShow.begin();
	// 			std::advance(itEnd, begin);
	// 			m_CurveShow.erase(itBegin, itEnd);
	// 		}
	// 		if (end - begin > 0 && end - begin < (int)m_CurveShow.size() - 1)
	// 		{
	// 			auto itBegin = m_CurveShow.begin();
	// 			auto itEnd = m_CurveShow.end();
	// 			std::advance(itBegin, end - begin);
	// 			m_CurveShow.erase(itBegin, itEnd);
	// 		}
	// 
	// 		QVector<double>	m_vctGridX, vctY;
	// 		for (auto itCurve = m_CurveShow.begin(); itCurve != m_CurveShow.end(); itCurve++) {
	// 
	// 			m_vctGridX.push_back(itCurve->expire);
	// 			vctY.push_back(itCurve->price);
	// 		}
	// 
	// 		BONDTRADEINFO bti;
	// 		CBondContainer& container = CBondContainer::instance();
	// 		std::list<MarketStreamInfo>::iterator it2;
	// 		time_t t = ServerTimeMgr::instance().serverTime();
	// 		for (it2 = m_chartDistData.m_Stream.m_list.begin(); it2 != m_chartDistData.m_Stream.m_list.end(); it2++) {
	// 			int bondIndex = container.GetBondIndex(it2->m_body.m_bondkey, it2->m_body.m_listedmarket);
	// 			if (!container.IsValidIndex(bondIndex))continue;
	// 			const CBondInfo& info = container.ElementAtR(bondIndex);
	// 			memset(&bti, 0, sizeof(BONDTRADEINFO));
	// 			if (atoi(it2->m_body.m_exercise) == 1) {//到期
	// 				bti.expire = info.GetRemainYear(t);
	// 			}
	// 			else {//行权
	// 				bti.expire = info.GetRemainYearToOption(t);
	// 			}
	// 
	// 			if (bti.expire < 1.0000)bti.expire *= 4;
	// 			else bti.expire += 3;
	// 			bti.moditytime = it2->m_modify_time;
	// 			if (strlen(it2->m_body.m_yield) > 0) {
	// 				bti.price = atof(it2->m_body.m_yield);
	// 				FIELDCOPY(bti.sprice, it2->m_body.m_yield);
	// 			}
	// 			bti.brokerid = atoi(it2->m_company_id);
	// 			FIELDCOPY(bti.operate, it2->m_operate);
	// 			FIELDCOPY(bti.code, info.GetBondCode());
	// 			FIELDCOPY(bti.key, info.GetBondKey());
	// 			FIELDCOPY(bti.shortname, info.GetBondShortName());
	// 			FIELDCOPY(bti.remain, info.GetRemainPeriod(t));
	// 			FIELDCOPY(bti.rating, info.GetIssuerRating());
	// 			m_StreamShow.push_back(bti);
	// 		}
	// 		m_StreamShow.sort();
	// 
	// 		m_nLinePNum = m_CurveShow.size();
	// 		if (m_nLinePNum > 0) {
	// 			if (m_pLineP)delete[] m_pLineP;
	// 			m_pLineP = new QPointF[m_nLinePNum];
	// 		}
	// 		m_nPointNum = m_StreamShow.size();
	// 		if (m_nPointNum > 0) {
	// 			if (m_pPoints)delete[] m_pPoints;
	// 			m_pPoints = new QPointF[m_nPointNum];
	// 		}
	// 
	// 		customPlot->graph(0)->setData(m_vctGridX, vctY);
	// 
	// 		m_dMinX = 0;
	// 		m_dMaxX = 53;
	// 		if (m_CurveShow.size() > 0) {
	// 			m_dMaxX = m_CurveShow.back().expire;
	// 			m_dMinX = m_CurveShow.front().expire;
	// 			if (m_StreamShow.size() > 0) m_dMaxX = max(m_dMaxX, m_StreamShow.back().expire);
	// 		}
	// 
	// 		GetShowLimit(m_dMinX, m_dMaxX, m_dMinY, m_dMaxY);
	// 		customPlot->yAxis->setRange(m_dMinY, m_dMaxY);
	// 
	// 		double dExt = (m_dMaxX - m_dMinX) / 20;
	// 		customPlot->xAxis->setRange(m_dMinX, m_dMaxX + dExt);
	// 
	// 		int i = 0;
	// 		std::list<BONDRATE>::iterator it3;
	// 		for (it3 = m_CurveShow.begin(); it3 != m_CurveShow.end(); it3++, i++) {
	// 			m_pLineP[i].setX(customPlot->xAxis->coordToPixel(it3->expire));
	// 			m_pLineP[i].setY(customPlot->yAxis->coordToPixel(it3->price));
	// 		}
	// 
	// 		i = 0;
	// 		QVector<double> vctInX, vctInY, vctOutX, vctOutY;
	// 		std::list<BONDTRADEINFO>::iterator it4;
	// 		for (it4 = m_StreamShow.begin(); it4 != m_StreamShow.end(); it4++, i++) {
	// 			if (i >= m_nPointNum) break;
	// 
	// 			if (t - it4->moditytime <= 3600) {
	// 				vctInX.push_back(it4->expire);
	// 				vctInY.push_back(it4->price);
	// 			}
	// 			else if (t - it4->moditytime > 3600) {
	// 				vctOutX.push_back(it4->expire);
	// 				vctOutY.push_back(it4->price);
	// 			}
	// 
	// 			m_pPoints[i].setX(customPlot->xAxis->coordToPixel(it4->expire));
	// 			m_pPoints[i].setY(customPlot->yAxis->coordToPixel(it4->price));
	// 		}
	// 
	// 		if (type_All == m_type)
	// 		{
	// 			customPlot->graph(1)->setVisible(false);
	// 			customPlot->graph(2)->setVisible(false);
	// 
	// 			QString qText = tr("收益率");
	// 			bcte->setText(qText);
	// 
	// 			if (m_CurveShow.size() > 0 && (m_dDragLeft == 0.0 && m_dDragRight == 0.0 || bFirst))
	// 			{
	// 				int end = m_nEnd;
	// 				if (m_nEnd == 0)
	// 				{
	// 					end = m_dOriginMaxX;
	// 				}
	// 
	// 				bcde->setPos(getXPos_Value(m_nBegin), getXPos_Value(end));
	// 			}
	// 		}
	// 		else
	// 		{
	// 			customPlot->graph(1)->setVisible(true);
	// 			customPlot->graph(2)->setVisible(true);
	// 
	// 			customPlot->graph(1)->setData(vctOutX, vctOutY);
	// 			customPlot->graph(2)->setData(vctInX, vctInY);
	// 
	// 			QString qText1 = tr("当日成交(一小时内)");
	// 			QString qText2 = tr("当日成交(一小时前)");
	// 			bcte->setText(qText1, qText2);
	// 
	// 			if (m_CurveShow.size() > 0 && (m_dDealDragLeft == 0.0 && m_dDealDragRight == 0.0 || bFirst))
	// 			{
	// 				int end = m_nDealEnd;
	// 				if (m_nDealEnd == 0)
	// 				{
	// 					end = m_dOriginMaxX;
	// 				}
	// 
	// 				bcde->setPos(getXPos_Value(m_nDealBegin), getXPos_Value(end));
	// 			}
	// 		}
	// 
	// 		customPlot->replot(BaseChartCustomPlot::rpQueuedReplot);
}

void BondDealChart::clearCurrentCurve()
{
	// 		m_chartDistData.m_Curve.m_List.clear();
	// 		memset(m_chartDistData.m_Curve.m_CurveType, 0, sizeof(char) * 32);
	// 		memset(m_chartDistData.m_Curve.m_CurveName, 0, sizeof(char) * 64);
	// 		memset(m_chartDistData.m_Curve.m_CurveName_En, 0, sizeof(char) * 256);
}

void BondDealChart::GetShowLimit(double fMinXShow, double fMaxXShow, double& fMinYShow, double& fMaxYShow) {
	fMinYShow = 1000;
	fMaxYShow = -1000;

	bool bBegin = true;
	std::list<BONDRATE>::iterator it;
	int i = 0;
	bool bend = false;
	for (it = m_CurveShow.begin(); it != m_CurveShow.end(); it++, i++) {
		if (it->expire >= fMinXShow) {
			if (it->expire <= fMaxXShow) {
				if (bBegin) {
					if (i == 0) {
						fMinYShow = min(fMinYShow, it->price);
						fMaxYShow = max(fMaxYShow, it->price);
					}
					else {
						it--;
						BONDRATE lastbr = *it;
						it++;
						double fp = (lastbr.price - it->price) * (fMinXShow - it->expire) / (lastbr.expire - it->expire) + it->price;
						fMinYShow = min(fMinYShow, fp);
						fMaxYShow = max(fMaxYShow, fp);
						fMinYShow = min(fMinYShow, it->price);
						fMaxYShow = max(fMaxYShow, it->price);
					}
					bBegin = false;
				}
				else {
					fMinYShow = min(fMinYShow, it->price);
					fMaxYShow = max(fMaxYShow, it->price);
				}
			}
			else {
				if (!bend) {
					if (i == 0) {
						fMinYShow = min(fMinYShow, it->price);
						fMaxYShow = max(fMaxYShow, it->price);
					}
					else {
						if (bBegin) {
							it--;
							BONDRATE lastbr = *it;
							it++;
							double fp = (it->price - lastbr.price) * (fMaxXShow - lastbr.expire) / (it->expire - lastbr.expire) + lastbr.price;
							fMinYShow = min(fMinYShow, fp);
							fMaxYShow = max(fMaxYShow, fp);
							fp = (it->price - lastbr.price) * (fMinXShow - lastbr.expire) / (it->expire - lastbr.expire) + lastbr.price;
							fMinYShow = min(fMinYShow, fp);
							fMaxYShow = max(fMaxYShow, fp);
						}
						else {
							it--;
							BONDRATE lastbr = *it;
							it++;
							double fp = (it->price - lastbr.price) * (fMaxXShow - lastbr.expire) / (it->expire - lastbr.expire) + lastbr.price;
							fMinYShow = min(fMinYShow, fp);
							fMaxYShow = max(fMaxYShow, fp);
						}
					}
					bend = true;
				}
			}
		}
	}

	std::list<BONDTRADEINFO>::iterator it2;
	for (it2 = m_StreamShow.begin(); it2 != m_StreamShow.end(); it2++) {
		if (it2->expire >= fMinXShow && it2->expire <= fMaxXShow) {
			fMinYShow = min(fMinYShow, it2->price);
			fMaxYShow = max(fMaxYShow, it2->price);
		}
	}

	if (fMaxYShow < 0) {
		fMinYShow = 3;
		fMaxYShow = 7;
		return;
	}

	if (fMinYShow >= 0) fMinYShow = (int)(fMinYShow * 4) / 4.0;
	else fMinYShow = (int)(fMinYShow * 4) / 4.0 - 0.25;
	fMaxYShow = (int)(fMaxYShow * 4) / 4.0 + 0.25;
}

// 	void BondDealChart::DecodeMarketStreamUnit(MarketStreamInfo& stInfo, const xQBMarketStreamUnit_c& unit)
// 	{
// 		memset(&stInfo, 0, sizeof(MarketStreamInfo));
// 		FIELDCOPY(stInfo.m_company_id, unit.m_company_id);
// 		FIELDCOPY(stInfo.m_dept, unit.m_dept);
// 		FIELDCOPY(stInfo.m_type, unit.m_type);
// 		FIELDCOPY(stInfo.m_operate, unit.m_operate);
// 		FIELDCOPY(stInfo.m_status, unit.m_status);
// 		FIELDCOPY(stInfo.m_body.m_bondkey, unit.m_body2.m_bondkey);
// 		FIELDCOPY(stInfo.m_body.m_listedmarket, unit.m_body2.m_listedmarket);
// 		FIELDCOPY(stInfo.m_body.m_price, SSTools::PriceRemoveZero(unit.m_body2.m_price, 0).c_str());
// 		FIELDCOPY(stInfo.m_body.m_volume, unit.m_body2.m_volume);
// 		FIELDCOPY(stInfo.m_body.m_fullPrice, unit.m_body2.m_fullPrice);
// 		FIELDCOPY(stInfo.m_body.m_cleanPrice, unit.m_body2.m_cleanPrice);
// 		FIELDCOPY(stInfo.m_body.m_yield, unit.m_body2.m_yield);
// 		FIELDCOPY(stInfo.m_body.m_rebate, unit.m_body2.m_rebate);
// 		FIELDCOPY(stInfo.m_body.m_return_point, unit.m_body2.m_return_point);
// 		FIELDCOPY(stInfo.m_body.m_id, unit.m_body2.m_id);
// 		FIELDCOPY(stInfo.m_body.m_dealStatus, unit.m_body2.m_dealStatus);
// 		FIELDCOPY(stInfo.m_body.m_exercise, unit.m_body2.m_exercise);
// 		stInfo.m_body.m_createTime = unit.m_body2.m_createTime;
// 		stInfo.m_modify_time = unit.m_modify_time;
// 		stInfo.m_create_time = unit.m_create_time;
// 		stInfo.m_indexID = unit.m_indexID;
// 	}

int BondDealChart::GetDate(const char* cDate)
{
	if (!cDate || strlen(cDate) <= 0) return 0;
	QString szTemp, szUnit, szValue;
	szTemp = QString("%1").arg(cDate);
	szUnit = szTemp.right(1);
	szValue = szTemp.left(szTemp.length() - 1);
	if (szUnit == "Y") {
		return szValue.toInt() * 365;
	}
	else if (szUnit == "M") {
		return szValue.toInt() * 30;
	}
	else if (szUnit == "D") {
		return szValue.toInt();
	}
	else {
		return 0;
	}
}

double BondDealChart::getXPos_Value(double value)
{
	QB_CHECK_RETURN_VALUE(bcde, 0);

	if (m_dOriginMaxX - m_dOriginMinX == 0) return 0;
	return (value - m_dOriginMinX) / (m_dOriginMaxX - m_dOriginMinX) * bcde->rect().width();
}

void BondDealChart::paintEvent(QPaintEvent* event)
{
	QStylePainter painter(this);

	painter.fillRect(rect(), StyleMgr::instance().color("BasicPlate"));
}

void BondDealChart::leaveEvent(QEvent* event)
{
	QB_CHECK_RETURN_VOID1(customPlot);

	customPlot->replot();
}

void BondDealChart::onMouseMove(QMouseEvent* event)
{
	QB_CHECK_RETURN_VOID1(customPlot && customPlot->graph(0) && m_pLineP);

	double dm = customPlot->graph(0)->selectTest(event->pos(), false);
	if (0 < dm && 2 > dm)
	{
		QPen pen(QColor(225, 146, 0));
		pen.setWidth(2);
		customPlot->graph(0)->setPen(pen);
	}
	else
	{
		QPen pen(QColor(205, 119, 4));
		pen.setWidth(1);
		customPlot->graph(0)->setPen(pen);
	}

	customPlot->replot();

	int left = customPlot->yAxis->axisRect()->left();
	int right = customPlot->yAxis->axisRect()->right();

	int x = mapFromGlobal(event->screenPos().toPoint()).x() - 8;
	int y = mapFromGlobal(event->screenPos().toPoint()).y() - 8;

	QPointF* p = m_pPoints;
	int nHot = -1;

	std::list<int> lp;
	for (int i = 0; i < m_nPointNum; i++, p++) {
		if (p->x() >= left && p->x() <= right) {
			if ((x - p->x()) * (x - p->x()) + (y - p->y()) * (y - p->y()) < 36) {
				lp.push_back(i);
			}
		}
	}
	if (lp.size() > 0) {
		CBondTradeInfoList dataList;
		int i = 0;
		std::list<int>::iterator iti;
		std::list<BONDTRADEINFO>::iterator it;
		int nLast = -1;
		int nMinT = -1;
		time_t t = ServerTimeMgr::instance().serverTime();
		QString strComparePrc;
		for (iti = lp.begin(); iti != lp.end(); iti++) {
			i = 0;
			for (it = m_StreamShow.begin(); it != m_StreamShow.end(); it++, i++) {
				if (i == *iti) {
					int dt = t - it->moditytime;
					if (nMinT < 0) {
						nMinT = dt;
						nLast = i;
						strComparePrc = QString("%1").arg(it->sprice);
					}
					else if (dt < nMinT) {
						nMinT = dt;
						nLast = i;
						strComparePrc = QString("%1").arg(it->sprice);
					}
					break;
				}
			}
		}
		if (nLast >= 0) {
			i = 0;
			for (it = m_StreamShow.begin(); it != m_StreamShow.end(); it++, i++) {
				if (i == nLast) {
					int nNumb = 0;
					for (std::list<BONDTRADEINFO>::iterator itLoop = m_StreamShow.begin(); itLoop != m_StreamShow.end(); itLoop++) {
						QString strCmp(itLoop->sprice);
						if (strComparePrc == strCmp) {
							nNumb++;
						}
					}

					m_nHotPoint = i;
					p = &m_pPoints[i];

					QString szTip;
					BONDTRADEINFO bti;
					bti = *it;

					if (bti.brokerid == 50) {
						szTip = QString("收益率 %1%").arg(it->sprice);

						std::vector<QBTipCustomItem> vctCustomItem;
						QBTipCustomItem item;
						item.row = 0;
						item.col = 1;
						item.clrNormal = QColor(223, 174, 76, 255);
						vctCustomItem.push_back(item);
						QBTips::showText(event->screenPos().toPoint(), szTip, this, &vctCustomItem);
					}
					else {
						szTip = QString("收益率 %1% 成交笔数 %2").arg(it->sprice).arg(nNumb);

						std::vector<QBTipCustomItem> vctCustomItem;
						QBTipCustomItem item;
						item.row = 0;
						item.col = 1;
						item.clrNormal = QColor(223, 174, 76, 255);
						vctCustomItem.push_back(item);
						item.col = 3;
						vctCustomItem.push_back(item);
						QBTips::showText(event->screenPos().toPoint(), szTip, this, &vctCustomItem);
					}

					break;
				}
			}
			return;
		}
	}

	p = m_pLineP;
	for (int i = 0; i < m_nLinePNum; i++, p++) {
		if (p->x() >= left && p->x() <= right) {
			if ((x - p->x()) * (x - p->x()) + (y - p->y()) * (y - p->y()) < 16) {
				if (m_nHotPoint != i) {
					m_nHotPoint = i;

					QString szTip;
					std::list<BONDRATE>::iterator it;
					int j = 0;
					for (it = m_CurveShow.begin(); it != m_CurveShow.end(); it++, j++) {
						if (i == j) {
							if (it->expire >= 4) {
								if ((it->expire - (int)(it->expire)) < 0.02) {
									szTip = QString::asprintf("%dY %.4f%%  ", (int)it->expire - 3, it->price);
								}
								else {
									szTip = QString::asprintf("%.1fY %.4f%%  ", it->expire - 3, it->price);
								}
							}
							else {
								if (it->expire <= 0.0001) {
									szTip = QString::asprintf("0D %.4f%%  ", it->price);
								}
								else if (it->expire < 0.333) {
									szTip = QString::asprintf("%dD %.4f%%  ", (int)(it->expire * 3 * 30 + 0.5f), it->price);
								}
								else {
									szTip = QString::asprintf("%dM %.4f%%  ", (int)(it->expire * 3 + 0.5f), it->price);
								}
							}
							break;
						}
					}
					if (szTip.length() > 0) {
						std::vector<QBTipCustomItem> vctCustomItem;
						QBTipCustomItem item;
						item.row = 0;
						item.col = 1;
						item.clrNormal = QColor(223, 174, 76, 255);
						vctCustomItem.push_back(item);
						QBTips::showText(event->screenPos().toPoint(), szTip, this, &vctCustomItem);
					}
				}
				return;
			}
		}
	}

	if (m_nHotPoint >= 0) {
		m_nHotPoint = -1;
		QBTips::hideTip();
	}
}